package com.alibaba.citrus.cr.mn.order.center.facade.function.convert;

import com.alibaba.citrus.cr.common.enums.ordercenter.DictionaryTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderBusinessTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrgTypeEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CargoZoneAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CustomerSaleScopeAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.LogisticWarehouseQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.SearchScItemQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.BaseDataScItemDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.LogisticWarehouseQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.SalesBizOrgQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.function.dataobject.AtomOrderDO;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crplatformenhance.api.organizationquery.dto.GetOrganizationsByOutCodesRequest;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.service.MnOrderCenterService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName SalesOrderParamsConvertService
 * @description: TODO
 * @date 2023/05/17 15:27
 * @version: 1.0
 */
@Service
public class ReturnOrderParamsConvertService extends AbstractOrderParamsConvertService<ReturnOrderAtomCreateRequest, AtomOrderDO>{

    @Resource
    private CustomerSaleScopeAdapter customerSaleScopeAdapter;
    @Resource
    private OrganizationQueryService organizationQueryService;
    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;
    @Resource
    private BcOrderService bcOrderService;
    @Resource
    private BaseDataService baseDataService;
    @Resource
    private UnifiedInventoryService unifiedInventoryService;

    @Resource
    private MnOrderCenterService mnOrderCenterService;

    @Resource
    private CargoZoneAdapter cargoZoneAdapter;

    @Override
    public List<AtomOrderDO> convert(List<ReturnOrderAtomCreateRequest> requestList) {
        List<AtomOrderDO> orderDOS = ReturnOrderAtomCreateRequestToAtomOrderDOConvertor.convert(requestList);

        // 查询货品信息，进行code转id
        List<String> scItemCodes = new ArrayList<>();
        orderDOS.forEach(o -> scItemCodes.addAll(o.getOrderLines().stream().map(OrderLine::getScItemId).distinct().collect(Collectors.toList())));
        Map<String, BaseDataScItemDTO> baseDataScItemMap = queryScItemInfo(scItemCodes);

        // 业务单元Code、组织Code、部门Code、渠道Code
        Map<String, SalesBizOrgQueryDTO> organizationByCodes = findSalesOrgByAtomOrderDO(orderDOS);
        Map<String, String> organizationIdByCodes = Maps.newHashMap();
        organizationByCodes.forEach((code, dto)->{
            organizationIdByCodes.put(code, String.valueOf(dto.getId()));
        });

        List<DictionaryResponse> businessTypeResponseList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_TYPE.getCode());
        Map<String, DictionaryResponse> businessTypeMap = businessTypeResponseList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (k1, k2) -> k2));

        List<DictionaryResponse> businessUnitList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_UNIT_CODE.getCode());
        Map<String, DictionaryResponse> businessUnitMap = businessUnitList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (x1, x2) -> x2));

        Map<String, WarehouseInfo> cacheWarehouseMap = Maps.newHashMap();
        for (AtomOrderDO orderDO : orderDOS) {
            String orgBisUnitCodeId = organizationIdByCodes.get(orderDO.getOrder().getBisUnitCode());
            String salesOrgKey = SalesOrgTypeEnum.SALES_ORG.getCode() + "_" + orderDO.getOrder().getOrganizationCode();
            if (OrderCategoryEnum.GROUP.getCode().equals(orderDO.getOrder().getOrderCategoryCode())) {
                salesOrgKey = orderDO.getOrder().getOrganizationCode();
            }
            String orgOrganizationCodeId = organizationIdByCodes.get(salesOrgKey);
            String orgDepartmentCodeId = organizationIdByCodes.get(orderDO.getOrder().getDepartmentCode());
            String orgSaleChannelCodeId = organizationIdByCodes.get(orderDO.getOrder().getSaleChannelCode());

            // 当前明细逻辑仓 为同一个
            WarehouseInfo warehouse = queryLgWarehouseInfo2(orderDO.getOrderLines().get(0), cacheWarehouseMap);
            // 主单 逻辑仓转换Code->ID
            orderDO.getOrder().setWareHouseCode(warehouse.getId());
            orderDO.getOrder().setWareHouseName(warehouse.getName());
            orderDO.getOrder().setWareHouseOutCode(warehouse.getCode());
            if (orderDO.getOrder().getBusinessType() != null) {
                if (businessTypeMap.containsKey(orderDO.getOrder().getBusinessType().toString())) {
                    orderDO.getOrder().setBusinessTypeName(businessTypeMap.get(orderDO.getOrder().getBusinessType().toString()).getName());
                }
            }
            if (StringUtils.isNotBlank(orderDO.getOrder().getBisUnitCode())) {
                // SalesBizOrgQueryDTO organizationSDO = organizationByCodes.get(orderDO.getOrder().getBisUnitCode());
                DictionaryResponse dictionaryResponse = businessUnitMap.get(orderDO.getOrder().getBisUnitCode());
                if (dictionaryResponse != null) {
                    orderDO.getOrder().setBisUnitName(dictionaryResponse.getName());
                }
            }
            String features = orderDO.getOrder().getFeatures();
            Map<String, String> featuresMap = JSONObject.parseObject(features, new TypeReference<Map<String, String>>() {
            });
            featuresMap = Optional.ofNullable(featuresMap).orElse(Maps.newHashMap());
            featuresMap.put("logicWarehouseCode", warehouse.getCode());

            // 新增OutCode
            orderDO.getOrder().setBisUnitOutCode(orderDO.getOrder().getBisUnitCode());
            orderDO.getOrder().setOrganizationOutCode(orderDO.getOrder().getOrganizationCode());
            orderDO.getOrder().setDepartmentOutCode(orderDO.getOrder().getDepartmentCode());
            orderDO.getOrder().setSaleChannelOutCode(orderDO.getOrder().getSaleChannelCode());
            orderDO.getOrder().setChannelOutCode(orderDO.getOrder().getChannelCode());

            // 重设为内部ID，兼容订单共享平台逻辑
            orderDO.getOrder().setBisUnitCode(orgBisUnitCodeId);
            orderDO.getOrder().setOrganizationCode(orgOrganizationCodeId);
            orderDO.getOrder().setDepartmentCode(orgDepartmentCodeId);
            orderDO.getOrder().setSaleChannelCode(orgSaleChannelCodeId);
            orderDO.getOrder().setReceiveWareHouseOutCode(orderDO.getOrder().getReceiveWareHouseCode());

            orderDO.getOrder().setFeatures(JSONObject.toJSONString(featuresMap));

            for (OrderLine orderLine : orderDO.getOrderLines()) {
                Map<String, String> lineFeaturesMap = JSONObject.parseObject(orderLine.getFeatures(), new TypeReference<Map<String, String>>() {
                });
                lineFeaturesMap = Optional.ofNullable(lineFeaturesMap).orElse(Maps.newHashMap());
                lineFeaturesMap.put("productCode", orderLine.getScItemId());
                lineFeaturesMap.put("logicWarehouseCode", warehouse.getCode());

                // 新增OutCode
                orderLine.setShippingWarehouseOutCode(warehouse.getCode());

                orderLine.setFeatures(JSONObject.toJSONString(lineFeaturesMap));

                // 货品Code转id
                BaseDataScItemDTO baseDataScItemDTO = baseDataScItemMap.get(orderLine.getScItemId());
                if (Objects.isNull(baseDataScItemDTO)) {
                    throw new FunctionException("OC-01-001-01-16-012", orderLine.getScItemId());
                }
                // 将物料编码转为ID
                orderLine.setScItemId(baseDataScItemDTO.getScItemId());
                orderLine.setShippingWarehouseCode(warehouse.getId());
                orderLine.setShippingWarehouseName(warehouse.getName());
                orderLine.setShippingWarehouseOutCode(warehouse.getCode());
            }
        }
        return orderDOS;
    }

    public WarehouseInfo queryLgWarehouseInfo2(OrderLine orderLine, Map<String, WarehouseInfo> cacheWarehouseMap) {
        String shippingWarehouseCode = orderLine.getShippingWarehouseCode();
        if (StringUtils.isBlank(shippingWarehouseCode)) {

            // 查看是否已经缓存 工厂+库存地点
            String key = String.format("%s_%s", orderLine.getDeliveryFactoryCode(), orderLine.getStockCode());
            WarehouseInfo warehouseInfo = cacheWarehouseMap.get(key);
            if (Objects.nonNull(warehouseInfo)) {
                return warehouseInfo;
            }
            List<LogisticWarehouseQueryRequest> logisticWarehouseQueryRequests = Lists.newArrayList();
            LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
            queryRequest.setFactoryCode(orderLine.getDeliveryFactoryCode());
            queryRequest.setStorageLocation(orderLine.getStockCode());
            logisticWarehouseQueryRequests.add(queryRequest);
            List<LogisticWarehouseQueryDTO> listResult = cargoZoneAdapter.queryCargoZoneListByParam(logisticWarehouseQueryRequests);

            if (CollectionUtils.isEmpty(listResult)) {
                throw new FunctionException("OC-01-001-01-16-010", String.format("工厂编码:%s, 库存地点编码:%s",
                        orderLine.getDeliveryFactoryCode(),
                        orderLine.getStockCode()));
            }
            LogisticWarehouseQueryDTO queryWarehouseInfo = listResult.get(0);
            warehouseInfo = new WarehouseInfo();
            warehouseInfo.setId(queryWarehouseInfo.getId());
            warehouseInfo.setWarehouseId(queryWarehouseInfo.getWarehouseId());
            warehouseInfo.setCode(queryWarehouseInfo.getCode());
            warehouseInfo.setName(queryWarehouseInfo.getName());
            warehouseInfo.setWarehouseCode(queryWarehouseInfo.getWarehouseCode());
            warehouseInfo.setSapFactoryCode(queryWarehouseInfo.getSapFactoryCode());

            // (缓存)交货工厂编码+交货库存地点 填充
            cacheWarehouseMap.put(key, warehouseInfo);
            return warehouseInfo;
        }

        // 查看是否已经缓存 逻辑仓库
        WarehouseInfo warehouseInfo = cacheWarehouseMap.get(shippingWarehouseCode);
        if (Objects.nonNull(warehouseInfo)) {
            return warehouseInfo;
        }

        // 若 逻辑仓已传，需要通过Code转换ID处理

        LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
        queryRequest.setLogicWarehouseCode(orderLine.getShippingWarehouseCode());
        List<LogisticWarehouseQueryRequest> logisticWarehouseQueryRequests = Lists.newArrayList(queryRequest);
        List<LogisticWarehouseQueryDTO> listResult = cargoZoneAdapter.queryCargoZoneListByParam(logisticWarehouseQueryRequests);

        if (CollectionUtils.isNotEmpty(listResult)) {
            LogisticWarehouseQueryDTO queryWarehouseInfo = listResult.get(0);

            warehouseInfo = new WarehouseInfo();
            warehouseInfo.setId(queryWarehouseInfo.getId());
            warehouseInfo.setWarehouseId(queryWarehouseInfo.getWarehouseId());
            warehouseInfo.setCode(queryWarehouseInfo.getCode());
            warehouseInfo.setName(queryWarehouseInfo.getName());
            warehouseInfo.setWarehouseCode(queryWarehouseInfo.getWarehouseCode());
            warehouseInfo.setSapFactoryCode(queryWarehouseInfo.getSapFactoryCode());
            // (缓存) 逻辑仓库
            cacheWarehouseMap.put(shippingWarehouseCode, warehouseInfo);
            return warehouseInfo;
        }
        throw new FunctionException("OC-01-001-01-16-010", String.format("逻辑仓编码:%s", shippingWarehouseCode));
    }

    private Map<String, BaseDataScItemDTO> queryScItemInfo(List<String> scItemCodes) {
        if (CollectionUtils.isEmpty(scItemCodes)) {
            return Maps.newHashMap();
        }
        SearchScItemQueryRequest request = new SearchScItemQueryRequest();
        request.setPageNum(1);
        request.setPageSize(scItemCodes.size());

        Map<String, Object> searchReqDTO = Maps.newHashMap();
        searchReqDTO.put("outerIdList", scItemCodes);
        request.setSearchReqDTO(searchReqDTO);
        List<BaseDataScItemDTO> scItemDTOS = baseDataServiceAdapter.searchScItemByDBWhenDegraded(request);

        return Optional.ofNullable(scItemDTOS).orElse(Lists.newArrayList())
                .stream()
                .collect(Collectors.toMap(BaseDataScItemDTO::getOuterId, p -> p, (v1, v2) -> v1));
    }

    private Map<String, OrganizationSDO> queryOrganizations(List<String> bisUnitCodeList) {
        GetOrganizationsByOutCodesRequest getOrganizationsByOutCodesRequest = new GetOrganizationsByOutCodesRequest();
        getOrganizationsByOutCodesRequest.setOutCodes(bisUnitCodeList);
        Result<List<OrganizationSDO>> organResult = organizationQueryService.getOrganizationsByOutCodes(getOrganizationsByOutCodesRequest);
        if (CollectionUtils.isEmpty(organResult.getResult())) {
            return Maps.newHashMap();
        }
        return organResult.getResult().stream()
                .collect(Collectors.toMap(OrganizationSDO::getCode, p -> p, (v1, v2) -> v1));
    }

    private WarehouseInfo queryLgWarehouseInfo(OrderLine orderLine, Map<String, WarehouseInfo> cacheWarehouseMap) {
        String shippingWarehouseCode = orderLine.getShippingWarehouseCode();
        if (StringUtils.isBlank(shippingWarehouseCode)) {

            // 查看是否已经缓存 工厂+库存地点
            String key = String.format("%s_%s", orderLine.getDeliveryFactoryCode(), orderLine.getStockCode());
            WarehouseInfo warehouseInfo = cacheWarehouseMap.get(key);
            if (Objects.nonNull(warehouseInfo)) {
                return warehouseInfo;
            }

            // 当逻辑仓库信息为空时，通过 交货工厂编码+交货库存地点 填充
            SpecQueryWarehouseRequest cargoRequest = new SpecQueryWarehouseRequest();
            cargoRequest.setFactoryCode(orderLine.getDeliveryFactoryCode());
            cargoRequest.setInventoryCode(orderLine.getStockCode());
            cargoRequest.setModel(3);
            //销售单元仓 TODO 3.6 啥意思
            cargoRequest.setTypeList(Lists.newArrayList(3, 6));
            Result<List<WarehouseInfo>> cargoResponse = bcOrderService.specQueryWarehouse(cargoRequest);

            if (Objects.isNull(cargoResponse) || CollectionUtils.isEmpty(cargoResponse.getResult())) {
                throw new FunctionException("OC-01-001-01-16-009", String.format("工厂编码:%s, 库存地点编码:%s",
                        orderLine.getDeliveryFactoryCode(),
                        orderLine.getStockCode()));
            }
            WarehouseInfo queryWarehouseInfo = cargoResponse.getResult().get(0);
            // (缓存)交货工厂编码+交货库存地点 填充
            cacheWarehouseMap.put(key, queryWarehouseInfo);
            return queryWarehouseInfo;
        }

        // 查看是否已经缓存 逻辑仓库
        WarehouseInfo warehouseInfo = cacheWarehouseMap.get(shippingWarehouseCode);
        if (Objects.nonNull(warehouseInfo)) {
            return warehouseInfo;
        }

        // 若 逻辑仓已传，需要通过Code转换ID处理
        WmsQueryWarehouseZoneListRequest byIdRequest = new WmsQueryWarehouseZoneListRequest();
        byIdRequest.setCode(shippingWarehouseCode);
        WmsQueryWarehouseZoneListResponse response = unifiedInventoryService.wmsQueryWarehouseZoneList(byIdRequest);
        if (Objects.nonNull(response) && CollectionUtils.isNotEmpty(response.getResult())) {
            WarehouseInfo queryWarehouseInfo = response.getResult().get(0);
            // (缓存) 逻辑仓库
            cacheWarehouseMap.put(shippingWarehouseCode, queryWarehouseInfo);
            return queryWarehouseInfo;

        }
        throw new FunctionException("OC-01-001-01-16-009", String.format("逻辑仓编码:%s", shippingWarehouseCode));
    }

    /**
     * 根据code查询组织信息
     */
    private Map<String, String> getOrganizationByCodes(List<String> codes) {
        if (CollectionUtils.isEmpty(codes)) {
            return Maps.newHashMap();
        }
        BaselineGetOrganizationByCodes2Request request = new BaselineGetOrganizationByCodes2Request();
        request.setIds(codes);
        BaselineGetOrganizationByCodes2Response response = baseDataService.baselineGetOrganizationByCodes2(request);
        if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getResult())) {
            return new HashMap<>();
        }

        Map<String, String> codeIdMap = new HashMap<>();
        response.getResult().forEach(o -> codeIdMap.put(o.getCode(), o.getId()));
        return codeIdMap;
    }




    private Map<String, SalesBizOrgQueryResponse> queryOrganizations2(SalesOrderBizBatchCreateRequest salesOrderBizBatchCreateRequest) {

        List<SalesBizOrgByBuQueryRequest> salesBizOrgByBuQueryRequests = org.apache.commons.compress.utils.Lists.newArrayList();
        Set<String> notNormalBusinessOrg = Sets.newHashSet();

        for (SalesOrderBizCreateRequest createRequest : salesOrderBizBatchCreateRequest.getOrderList()) {
            String businessType = createRequest.getBusinessType();
            // 对于常温业态目前只支持 6000之下的组织查询
            if(SalesOrderBusinessTypeEnum.NORMAL_TEMPERATURE.equals(SalesOrderBusinessTypeEnum.of(businessType))){
                Set<String> currNormalSalesOrgCode = Sets.newHashSet();

                CollectionUtils.addIgnoreNull(currNormalSalesOrgCode, createRequest.getBusinessUnitCode());
                CollectionUtils.addIgnoreNull(currNormalSalesOrgCode, createRequest.getSalesOrganizationCode());
                CollectionUtils.addIgnoreNull(currNormalSalesOrgCode, createRequest.getSalesDepartmentCode());
                CollectionUtils.addIgnoreNull(currNormalSalesOrgCode, createRequest.getSalesChannelCode());
                for (String tmpNormalSalesOrgCode : currNormalSalesOrgCode) {

                    SalesBizOrgByBuQueryRequest buQueryRequest = new SalesBizOrgByBuQueryRequest();
                    buQueryRequest.setBuCode("6000");
                    buQueryRequest.setOrgCode(tmpNormalSalesOrgCode);
                    //SalesOrderBusinessTypeEnum.NORMAL_TEMPERATURE.getCode().toString();
                    buQueryRequest.setBusinessType(createRequest.getProductGroupCode());

                    salesBizOrgByBuQueryRequests.add(buQueryRequest);
                }
            } else {
                CollectionUtils.addIgnoreNull(notNormalBusinessOrg, createRequest.getBusinessUnitCode());
                CollectionUtils.addIgnoreNull(notNormalBusinessOrg, createRequest.getSalesOrganizationCode());
                CollectionUtils.addIgnoreNull(notNormalBusinessOrg, createRequest.getSalesDepartmentCode());
                CollectionUtils.addIgnoreNull(notNormalBusinessOrg, createRequest.getSalesChannelCode());
            }
        }

        if(CollectionUtils.isEmpty(notNormalBusinessOrg) && CollectionUtils.isEmpty(salesBizOrgByBuQueryRequests)) {
            return Maps.newHashMap();
        }

        Map<String, SalesBizOrgQueryResponse> orgMapByOrgCodes = querySalesBizOrgByOrgCodes(notNormalBusinessOrg);
        Map<String, SalesBizOrgQueryResponse> orgMapByBuAndOrgCodes = querySalesBizOrgByBuAndOrgCodes(salesBizOrgByBuQueryRequests);

        Map<String, SalesBizOrgQueryResponse> resultMap = Maps.newHashMap();
        resultMap.putAll(orgMapByOrgCodes);
        resultMap.putAll(orgMapByBuAndOrgCodes);
        return resultMap;
    }

    private Map<String, SalesBizOrgQueryResponse> querySalesBizOrgByBuAndOrgCodes(List<SalesBizOrgByBuQueryRequest> salesBizOrgByBuQueryRequests) {
        if(CollectionUtils.isNotEmpty(salesBizOrgByBuQueryRequests)) {
            FindSalesOrgByCodeAndBURequest buRequest = new FindSalesOrgByCodeAndBURequest();
            Result<List<SalesBizOrgQueryResponse>> listResult = mnOrderCenterService.findSalesOrgByCodeAndBU(buRequest);

            if(Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())) {
                return Maps.newHashMap();
            }

            return listResult.getResult().stream()
                    .collect(Collectors.toMap(SalesBizOrgQueryResponse::getOrgCode, p->p,(v1, v2)->v1));
        }
        return Maps.newHashMap();
    }

    private Map<String, SalesBizOrgQueryResponse> querySalesBizOrgByOrgCodes(Set<String> notNormalBusinessOrg) {
        if(CollectionUtils.isNotEmpty(notNormalBusinessOrg)) {
            SalesBizOrgQueryRequest salesOrgRequest = new SalesBizOrgQueryRequest();
            salesOrgRequest.setOrgCodeList(new ArrayList<>(notNormalBusinessOrg));
            Result<List<SalesBizOrgQueryResponse>> listResult = mnOrderCenterService.findSalesOrgByCodeList(salesOrgRequest);

            if(Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())) {
                return Maps.newHashMap();
            }

            return listResult.getResult().stream()
                    .collect(Collectors.toMap(SalesBizOrgQueryResponse::getOrgCode, p->p,(v1, v2)->v1));
        }
        return Maps.newHashMap();
    }


}
